/*!
 * \file WtPorter.cpp
 * \project WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief WonderTrader实盘Porter接口实现
 * 
 * \details 该文件实现了WonderTrader实盘交易系统的C语言Porter接口：
 *          - 提供跨语言调用的C接口实现
 *          - 封装WtRtRunner实盘运行器的功能
 *          - 实现CTA、HFT、SEL三种策略类型的完整接口
 *          - 支持策略上下文创建和管理
 *          - 支持实时行情数据获取和订阅
 *          - 支持交易下单、撤单、持仓查询等交易功能
 *          - 支持外部数据加载器和解析器扩展
 *          - 支持事件回调和异步处理
 *          - 支持日志记录和用户数据存储
 *          
 *          主要功能实现：
 *          - 系统初始化和配置管理
 *          - 策略工厂注册和管理
 *          - CTA策略接口实现：趋势跟踪策略
 *          - HFT策略接口实现：高频交易策略
 *          - SEL策略接口实现：选股策略
 *          - 行情解析器接口实现
 *          - 执行器接口实现
 *          - 外部数据加载接口实现
 */
#include "WtPorter.h"
#include "WtRtRunner.h"

#include "../WtCore/WtHelper.h"
#include "../WTSTools/WTSLogger.h"
#include "../Includes/WTSTradeDef.hpp"
#include "../Includes/WTSVersion.h"

#ifdef _WIN32
#   ifdef _WIN64
    char PLATFORM_NAME[] = "X64";
#   else
    char PLATFORM_NAME[] = "X86";
#endif
#else
    char PLATFORM_NAME[] = "UNIX";
#endif

/**
 * @brief 获取实盘运行器实例
 * @details 使用单例模式获取WtRtRunner实例，确保全局唯一
 * @return WtRtRunner& 实盘运行器引用
 */
WtRtRunner& getRunner()
{
	static WtRtRunner runner;
	return runner;
}

/**
 * @brief 注册事件回调函数
 * @details 注册系统事件回调，用于接收系统级事件通知
 * @param cbEvt 事件回调函数指针
 */
void register_evt_callback(FuncEventCallback cbEvt)
{
	getRunner().registerEvtCallback(cbEvt);
}

/**
 * @brief 注册CTA策略回调函数
 * @details 注册CTA(商品交易顾问)策略的各种回调函数
 * @param cbInit 策略初始化回调
 * @param cbTick tick数据回调
 * @param cbCalc 计算回调
 * @param cbBar K线数据回调
 * @param cbSessEvt 交易时段事件回调
 */
void register_cta_callbacks(FuncStraInitCallback cbInit, FuncStraTickCallback cbTick, FuncStraCalcCallback cbCalc, FuncStraBarCallback cbBar, FuncSessionEvtCallback cbSessEvt)
{
	getRunner().registerCtaCallbacks(cbInit, cbTick, cbCalc, cbBar, cbSessEvt);
}

/**
 * @brief 注册SEL策略回调函数
 * @details 注册SEL(选股)策略的各种回调函数
 * @param cbInit 策略初始化回调
 * @param cbTick tick数据回调
 * @param cbCalc 计算回调
 * @param cbBar K线数据回调
 * @param cbSessEvt 交易时段事件回调
 */
void register_sel_callbacks(FuncStraInitCallback cbInit, FuncStraTickCallback cbTick, FuncStraCalcCallback cbCalc, FuncStraBarCallback cbBar, FuncSessionEvtCallback cbSessEvt)
{
	getRunner().registerSelCallbacks(cbInit, cbTick, cbCalc, cbBar, cbSessEvt);
}

/**
 * @brief 注册HFT策略回调函数
 * @details 注册HFT(高频交易)策略的各种回调函数，包含更多交易相关回调
 * @param cbInit 策略初始化回调
 * @param cbTick tick数据回调
 * @param cbBar K线数据回调
 * @param cbChnl 通道回调
 * @param cbOrd 订单回调
 * @param cbTrd 成交回调
 * @param cbEntrust 委托回调
 * @param cbOrdDtl 订单明细回调
 * @param cbOrdQue 订单队列回调
 * @param cbTrans 逐笔成交回调
 * @param cbSessEvt 交易时段事件回调
 * @param cbPosition 持仓回调
 */
void register_hft_callbacks(FuncStraInitCallback cbInit, FuncStraTickCallback cbTick, FuncStraBarCallback cbBar, 
	FuncHftChannelCallback cbChnl, FuncHftOrdCallback cbOrd, FuncHftTrdCallback cbTrd, FuncHftEntrustCallback cbEntrust,
	FuncStraOrdDtlCallback cbOrdDtl, FuncStraOrdQueCallback cbOrdQue, FuncStraTransCallback cbTrans, FuncSessionEvtCallback cbSessEvt, FuncHftPosCallback cbPosition)
{
	getRunner().registerHftCallbacks(cbInit, cbTick, cbBar, cbChnl, cbOrd, cbTrd, cbEntrust, cbOrdDtl, cbOrdQue, cbTrans, cbSessEvt, cbPosition);
}

/**
 * @brief 注册解析器回调函数
 * @details 注册行情解析器的回调函数，用于处理行情数据解析事件
 * @param cbEvt 解析器事件回调
 * @param cbSub 订阅回调
 */
void register_parser_callbacks(FuncParserEvtCallback cbEvt, FuncParserSubCallback cbSub)
{
	getRunner().registerParserPorter(cbEvt, cbSub);
}

/**
 * @brief 注册执行器回调函数
 * @details 注册交易执行器的回调函数，用于处理交易执行相关事件
 * @param cbInit 执行器初始化回调
 * @param cbExec 执行命令回调
 */
void register_exec_callbacks(FuncExecInitCallback cbInit, FuncExecCmdCallback cbExec)
{
	getRunner().registerExecuterPorter(cbInit, cbExec);
}

/**
 * @brief 创建外部解析器
 * @details 创建指定ID的外部行情解析器实例
 * @param id 解析器ID
 * @return bool 创建是否成功
 */
bool create_ext_parser(const char* id)
{
	return getRunner().createExtParser(id);
}

/**
 * @brief 创建外部执行器
 * @details 创建指定ID的外部交易执行器实例
 * @param id 执行器ID
 * @return bool 创建是否成功
 */
bool create_ext_executer(const char* id)
{
	return getRunner().createExtExecuter(id);
}

/**
 * @brief 注册外部数据加载器
 * @details 注册外部数据加载器的各种回调函数，用于加载历史数据
 * @param fnlBarLoader 最终K线数据加载器
 * @param rawBarLoader 原始K线数据加载器
 * @param fctLoader 复权因子加载器
 * @param tickLoader tick数据加载器
 */
void register_ext_data_loader(FuncLoadFnlBars fnlBarLoader, FuncLoadRawBars rawBarLoader, FuncLoadAdjFactors fctLoader, FuncLoadRawTicks tickLoader)
{
	getRunner().registerExtDataLoader(fnlBarLoader, rawBarLoader, fctLoader, tickLoader);
}

/**
 * @brief 推送原始K线数据
 * @details 向系统推送原始K线数据，用于实时数据更新
 * @param bars K线数据数组
 * @param count 数据条数
 */
void feed_raw_bars(WTSBarStruct* bars, WtUInt32 count)
{
	getRunner().feedRawBars(bars, count);
}

/**
 * @brief 推送复权因子数据
 * @details 向系统推送复权因子数据，用于价格复权计算
 * @param stdCode 标准合约代码
 * @param dates 日期数组
 * @param factors 复权因子数组
 * @param count 数据条数
 */
void feed_adj_factors(WtString stdCode, WtUInt32* dates, double* factors, WtUInt32 count)
{
	getRunner().feedAdjFactors(stdCode, (uint32_t*)dates, factors, count);
}

/**
 * @brief 推送原始tick数据
 * @details 向系统推送原始tick数据（当前未实现）
 * @param ticks tick数据数组
 * @param count 数据条数
 */
void feed_raw_ticks(WTSTickStruct* ticks, WtUInt32 count)
{
	WTSLogger::error("API not implemented");
}

/**
 * @brief 初始化Porter接口
 * @details 初始化WonderTrader Porter接口，设置日志配置
 * @param logProfile 日志配置文件路径或配置内容
 * @param isFile 是否为文件路径（true）或配置内容（false）
 * @param genDir 生成文件目录
 */
void init_porter(const char* logProfile, bool isFile, const char* genDir)
{
	static bool inited = false;

	if (inited)
		return;

	getRunner().init(logProfile, isFile, genDir);

	inited = true;
}

/**
 * @brief 配置Porter接口
 * @details 配置WonderTrader Porter接口，加载系统配置
 * @param cfgfile 配置文件路径或配置内容
 * @param isFile 是否为文件路径（true）或配置内容（false）
 */
void config_porter(const char* cfgfile, bool isFile)
{
	if (strlen(cfgfile) == 0)
		getRunner().config("config.json", true);
	else
		getRunner().config(cfgfile, isFile);
}

/**
 * @brief 运行Porter接口
 * @details 启动WonderTrader Porter接口，开始实盘交易
 * @param bAsync 是否异步运行
 */
void run_porter(bool bAsync)
{
	getRunner().run(bAsync);
}

/**
 * @brief 释放Porter接口
 * @details 释放WonderTrader Porter接口资源，清理内存
 */
void release_porter()
{
	getRunner().release();
}

/**
 * @brief 获取版本信息
 * @details 获取WonderTrader版本信息，包含平台、版本号、编译时间
 * @return const char* 版本信息字符串
 */
const char* get_version()
{
	static std::string _ver;
	if (_ver.empty())
	{
		_ver = PLATFORM_NAME;
		_ver += " ";
		_ver += WT_VERSION;
		_ver += " Build@";
		_ver += __DATE__;
		_ver += " ";
		_ver += __TIME__;
	}
	return _ver.c_str();
}

/**
 * @brief 写入日志
 * @details 向系统日志写入指定级别的日志信息
 * @param level 日志级别
 * @param message 日志消息
 * @param catName 日志分类名称
 */
void write_log(WtUInt32 level, const char* message, const char* catName)
{
	if (strlen(catName) > 0)
	{
		WTSLogger::log_raw_by_cat(catName, (WTSLogLevel)level, message);
	}
	else
	{
		WTSLogger::log_raw((WTSLogLevel)level, message);
	}
}

/**
 * @brief 注册CTA策略工厂
 * @details 从指定目录加载并注册CTA策略工厂
 * @param factFolder 策略工厂目录路径
 * @return bool 注册是否成功
 */
bool reg_cta_factories(const char* factFolder)
{
	return getRunner().addCtaFactories(factFolder);
}

/**
 * @brief 注册SEL策略工厂
 * @details 从指定目录加载并注册SEL策略工厂
 * @param factFolder 策略工厂目录路径
 * @return bool 注册是否成功
 */
bool reg_sel_factories(const char* factFolder)
{
	return getRunner().addSelFactories(factFolder);
}

/**
 * @brief 注册HFT策略工厂
 * @details 从指定目录加载并注册HFT策略工厂
 * @param factFolder 策略工厂目录路径
 * @return bool 注册是否成功
 */
bool reg_hft_factories(const char* factFolder)
{
	return getRunner().addHftFactories(factFolder);
}

/**
 * @brief 注册执行器工厂
 * @details 从指定目录加载并注册执行器工厂
 * @param factFolder 执行器工厂目录路径
 * @return bool 注册是否成功
 */
bool reg_exe_factories(const char* factFolder)
{
	return getRunner().addExeFactories(factFolder);
}


#pragma region "CTA策略接口"

/**
 * @brief 创建CTA策略上下文
 * @details 创建指定名称的CTA策略上下文，用于策略运行
 * @param name 策略名称
 * @return CtxHandler 策略上下文句柄
 */
CtxHandler create_cta_context(const char* name)
{
	return getRunner().createCtaContext(name);
}

/**
 * @brief CTA策略开多仓
 * @details CTA策略执行开多仓操作
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param qty 开仓数量
 * @param userTag 用户标签
 * @param limitprice 限价（0表示市价）
 * @param stopprice 止损价（0表示不设止损）
 */
void cta_enter_long(CtxHandler cHandle, const char* stdCode, double qty, const char* userTag, double limitprice, double stopprice)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return;

	ctx->stra_enter_long(stdCode, qty, userTag, limitprice, stopprice);
}

/**
 * @brief CTA策略平多仓
 * @details CTA策略执行平多仓操作
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param qty 平仓数量
 * @param userTag 用户标签
 * @param limitprice 限价（0表示市价）
 * @param stopprice 止损价（0表示不设止损）
 */
void cta_exit_long(CtxHandler cHandle, const char* stdCode, double qty, const char* userTag, double limitprice, double stopprice)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return;

	ctx->stra_exit_long(stdCode, qty, userTag, limitprice, stopprice);
}

/**
 * @brief CTA策略开空仓
 * @details CTA策略执行开空仓操作
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param qty 开仓数量
 * @param userTag 用户标签
 * @param limitprice 限价（0表示市价）
 * @param stopprice 止损价（0表示不设止损）
 */
void cta_enter_short(CtxHandler cHandle, const char* stdCode, double qty, const char* userTag, double limitprice, double stopprice)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return;

	ctx->stra_enter_short(stdCode, qty, userTag, limitprice, stopprice);
}

/**
 * @brief CTA策略平空仓
 * @details CTA策略执行平空仓操作
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param qty 平仓数量
 * @param userTag 用户标签
 * @param limitprice 限价（0表示市价）
 * @param stopprice 止损价（0表示不设止损）
 */
void cta_exit_short(CtxHandler cHandle, const char* stdCode, double qty, const char* userTag, double limitprice, double stopprice)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return;

	ctx->stra_exit_short(stdCode, qty, userTag, limitprice, stopprice);
}

/**
 * @brief CTA策略获取K线数据
 * @details CTA策略获取指定合约的K线数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param period K线周期
 * @param barCnt K线条数
 * @param isMain 是否主K线
 * @param cb K线数据回调函数
 * @return WtUInt32 实际获取的K线条数
 */
WtUInt32 cta_get_bars(CtxHandler cHandle, const char* stdCode, const char* period, WtUInt32 barCnt, bool isMain, FuncGetBarsCallback cb)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return 0;
	try
	{
		WTSKlineSlice* kData = ctx->stra_get_bars(stdCode, period, barCnt, isMain);
		if (kData)
		{
			WtUInt32 reaCnt = (WtUInt32)kData->size();

			uint32_t blkCnt = kData->get_block_counts();
			for (uint32_t i = 0; i < blkCnt; i++)
			{
				if(kData->get_block_addr(i) != NULL)
					cb(cHandle, stdCode, period, kData->get_block_addr(i), kData->get_block_size(i), i == blkCnt - 1);
			}

			kData->release();
			return reaCnt;
		}
		else
		{
			return 0;
		}
	}
	catch (...)
	{
		return 0;
	}
}

/**
 * @brief CTA策略获取tick数据
 * @details CTA策略获取指定合约的tick数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param tickCnt tick数据条数
 * @param cb tick数据回调函数
 * @return WtUInt32 实际获取的tick条数
 */
WtUInt32	cta_get_ticks(CtxHandler cHandle, const char* stdCode, WtUInt32 tickCnt, FuncGetTicksCallback cb)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return 0;
	try
	{
		WTSTickSlice* tData = ctx->stra_get_ticks(stdCode, tickCnt);
		if (tData)
		{
			uint32_t thisCnt = min(tickCnt, (WtUInt32)tData->size());
			cb(cHandle, stdCode, (WTSTickStruct*)tData->at(0), thisCnt, true);
			tData->release();
			return thisCnt;
		}
		else
		{
			return 0;
		}
	}
	catch (...)
	{
		return 0;
	}
}

/**
 * @brief CTA策略获取持仓盈亏
 * @details CTA策略获取指定合约的持仓盈亏
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @return double 持仓盈亏
 */
double cta_get_position_profit(CtxHandler cHandle, const char* stdCode)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_position_profit(stdCode);
}

/**
 * @brief CTA策略获取明细进场时间
 * @details CTA策略获取指定合约明细的进场时间
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param openTag 开仓标签
 * @return WtUInt64 进场时间戳
 */
WtUInt64 cta_get_detail_entertime(CtxHandler cHandle, const char* stdCode, const char* openTag)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_detail_entertime(stdCode, openTag);
}

/**
 * @brief CTA策略获取明细成本
 * @details CTA策略获取指定合约明细的开仓成本
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param openTag 开仓标签
 * @return double 开仓成本
 */
double cta_get_detail_cost(CtxHandler cHandle, const char* stdCode, const char* openTag)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_detail_cost(stdCode, openTag);
}

/**
 * @brief CTA策略获取明细盈亏
 * @details CTA策略获取指定合约明细的盈亏
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param openTag 开仓标签
 * @param flag 盈亏标志
 * @return double 明细盈亏
 */
double cta_get_detail_profit(CtxHandler cHandle, const char* stdCode, const char* openTag, int flag)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_detail_profit(stdCode, openTag, flag);
}

/**
 * @brief CTA策略获取持仓均价
 * @details CTA策略获取指定合约的持仓均价
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @return double 持仓均价
 */
double cta_get_position_avgpx(CtxHandler cHandle, const char* stdCode)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_position_avgpx(stdCode);
}

/**
 * @brief CTA策略获取所有持仓
 * @details CTA策略获取所有合约的持仓信息
 * @param cHandle 策略上下文句柄
 * @param cb 持仓信息回调函数
 */
void cta_get_all_position(CtxHandler cHandle, FuncGetPositionCallback cb)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
	{
		cb(cHandle, "", 0, true);
		return;
	}

	ctx->enum_position([cb, cHandle](const char* stdCode, double qty) {
		cb(cHandle, stdCode, qty, false);
	});

	cb(cHandle, "", 0, true);
}

/**
 * @brief CTA策略获取持仓
 * @details CTA策略获取指定合约的持仓数量
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param bOnlyValid 是否只获取有效持仓
 * @param openTag 开仓标签
 * @return double 持仓数量
 */
double cta_get_position(CtxHandler cHandle, const char* stdCode, bool bOnlyValid, const char* openTag)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_position(stdCode, bOnlyValid, openTag);
}

/**
 * @brief CTA策略获取资金数据
 * @details CTA策略获取资金相关数据
 * @param cHandle 策略上下文句柄
 * @param flag 数据标志（0-动态权益，1-总平仓盈亏，2-总浮动盈亏，3-总手续费）
 * @return double 资金数据
 */
double cta_get_fund_data(CtxHandler cHandle, int flag)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_fund_data(flag);
}

/**
 * @brief CTA策略设置持仓
 * @details CTA策略直接设置指定合约的持仓数量
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param qty 目标持仓数量
 * @param userTag 用户标签
 * @param limitprice 限价（0表示市价）
 * @param stopprice 止损价（0表示不设止损）
 */
void cta_set_position(CtxHandler cHandle, const char* stdCode, double qty, const char* userTag, double limitprice, double stopprice)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return;

	ctx->stra_set_position(stdCode, qty, userTag, limitprice, stopprice);
}

/**
 * @brief CTA策略获取首次进场时间
 * @details CTA策略获取指定合约的首次进场时间
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @return WtUInt64 首次进场时间戳
 */
WtUInt64 cta_get_first_entertime(CtxHandler cHandle, const char* stdCode)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_first_entertime(stdCode);
}

/**
 * @brief CTA策略获取最后进场时间
 * @details CTA策略获取指定合约的最后进场时间
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @return WtUInt64 最后进场时间戳
 */
WtUInt64 cta_get_last_entertime(CtxHandler cHandle, const char* stdCode)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_last_entertime(stdCode);
}

/**
 * @brief CTA策略获取最后出场时间
 * @details CTA策略获取指定合约的最后出场时间
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @return WtUInt64 最后出场时间戳
 */
WtUInt64 cta_get_last_exittime(CtxHandler cHandle, const char* stdCode)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_last_exittime(stdCode);
}

/**
 * @brief CTA策略获取最后进场价格
 * @details CTA策略获取指定合约的最后进场价格
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @return double 最后进场价格
 */
double cta_get_last_enterprice(CtxHandler cHandle, const char* stdCode)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_last_enterprice(stdCode);
}

/**
 * @brief 获取合约最新价格
 * @details 获取指定合约的最新价格
 * @param stdCode 标准合约代码
 * @return double 最新价格
 */
double cta_get_price(const char* stdCode)
{
	return getRunner().getEngine()->get_cur_price(stdCode);
}

/**
 * @brief 获取当前交易日
 * @details 获取当前交易日期
 * @return WtUInt32 交易日期（YYYYMMDD格式）
 */
WtUInt32 cta_get_tdate()
{
	return getRunner().getEngine()->get_trading_date();
}

/**
 * @brief 获取当前日期
 * @details 获取当前日期
 * @return WtUInt32 当前日期（YYYYMMDD格式）
 */
WtUInt32 cta_get_date()
{
	return getRunner().getEngine()->get_date();
}

/**
 * @brief 获取当前时间
 * @details 获取当前时间
 * @return WtUInt32 当前时间（HHMM格式）
 */
WtUInt32 cta_get_time()
{
	return getRunner().getEngine()->get_min_time();
}

/**
 * @brief CTA策略记录日志
 * @details CTA策略记录自定义日志信息
 * @param cHandle 策略上下文句柄
 * @param message 日志消息
 */
void cta_log_text(CtxHandler cHandle, const char* message)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return;

	ctx->stra_log_info(message);
}

/**
 * @brief CTA策略保存用户数据
 * @details CTA策略保存用户自定义数据
 * @param cHandle 策略上下文句柄
 * @param key 数据键名
 * @param val 数据值
 */
void cta_save_userdata(CtxHandler cHandle, const char* key, const char* val)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return;

	ctx->stra_save_user_data(key, val);
}

/**
 * @brief CTA策略加载用户数据
 * @details CTA策略加载用户自定义数据
 * @param cHandle 策略上下文句柄
 * @param key 数据键名
 * @param defVal 默认值
 * @return WtString 数据值
 */
WtString cta_load_userdata(CtxHandler cHandle, const char* key, const char* defVal)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return defVal;

	return ctx->stra_load_user_data(key, defVal);
}

/**
 * @brief CTA策略订阅tick数据
 * @details CTA策略订阅指定合约的tick数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 */
void cta_sub_ticks(CtxHandler cHandle, const char* stdCode)
{
	CtaContextPtr ctx = getRunner().getCtaContext(cHandle);
	if (ctx == NULL)
		return;

	ctx->stra_sub_ticks(stdCode);
}

#pragma endregion

#pragma region "SEL策略接口"

/**
 * @brief 创建SEL策略上下文
 * @details 创建指定名称的SEL(选股)策略上下文，用于策略运行
 * @param name 策略名称
 * @param date 日期
 * @param time 时间
 * @param period 周期
 * @param trdtpl 交易模板（默认"CHINA"）
 * @param session 交易时段（默认"TRADING"）
 * @return CtxHandler 策略上下文句柄
 */
CtxHandler create_sel_context(const char* name, uint32_t date, uint32_t time, const char* period, const char* trdtpl/* = "CHINA"*/, const char* session/* = "TRADING"*/)
{
	return getRunner().createSelContext(name, date, time, period, trdtpl, session);
}

/**
 * @brief SEL策略保存用户数据
 * @details SEL策略保存用户自定义数据
 * @param cHandle 策略上下文句柄
 * @param key 数据键名
 * @param val 数据值
 */
void sel_save_userdata(CtxHandler cHandle, const char* key, const char* val)
{
	SelContextPtr ctx = getRunner().getSelContext(cHandle);
	if (ctx == NULL)
		return;

	ctx->stra_save_user_data(key, val);
}

/**
 * @brief SEL策略加载用户数据
 * @details SEL策略加载用户自定义数据
 * @param cHandle 策略上下文句柄
 * @param key 数据键名
 * @param defVal 默认值
 * @return WtString 数据值
 */
WtString sel_load_userdata(CtxHandler cHandle, const char* key, const char* defVal)
{
	SelContextPtr ctx = getRunner().getSelContext(cHandle);
	if (ctx == NULL)
		return defVal;

	return ctx->stra_load_user_data(key, defVal);
}

/**
 * @brief SEL策略记录日志
 * @details SEL策略记录自定义日志信息
 * @param cHandle 策略上下文句柄
 * @param message 日志消息
 */
void sel_log_text(CtxHandler cHandle, const char* message)
{
	SelContextPtr ctx = getRunner().getSelContext(cHandle);
	if (ctx == NULL)
		return;

	ctx->stra_log_info(message);
}

/**
 * @brief SEL策略获取合约价格
 * @details SEL策略获取指定合约的最新价格
 * @param stdCode 标准合约代码
 * @return double 最新价格
 */
double sel_get_price(const char* stdCode)
{
	return getRunner().getEngine()->get_cur_price(stdCode);
}

/**
 * @brief SEL策略获取当前日期
 * @details SEL策略获取当前日期
 * @return WtUInt32 当前日期（YYYYMMDD格式）
 */
WtUInt32 sel_get_date()
{
	return getRunner().getEngine()->get_date();
}

/**
 * @brief SEL策略获取当前时间
 * @details SEL策略获取当前时间
 * @return WtUInt32 当前时间（HHMM格式）
 */
WtUInt32 sel_get_time()
{
	return getRunner().getEngine()->get_min_time();
}

/**
 * @brief SEL策略获取所有持仓
 * @details SEL策略获取所有合约的持仓信息
 * @param cHandle 策略上下文句柄
 * @param cb 持仓信息回调函数
 */
void sel_get_all_position(CtxHandler cHandle, FuncGetPositionCallback cb)
{
	SelContextPtr ctx = getRunner().getSelContext(cHandle);
	if (ctx == NULL)
	{
		cb(cHandle, "", 0, true);
		return;
	}

	ctx->enum_position([cb, cHandle](const char* stdCode, double qty) {
		cb(cHandle, stdCode, qty, false);
	});

	cb(cHandle, "", 0, true);
}

/**
 * @brief SEL策略获取持仓
 * @details SEL策略获取指定合约的持仓数量
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param bOnlyValid 是否只获取有效持仓
 * @param openTag 开仓标签
 * @return double 持仓数量
 */
double sel_get_position(CtxHandler cHandle, const char* stdCode, bool bOnlyValid, const char* openTag)
{
	SelContextPtr ctx = getRunner().getSelContext(cHandle);
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_position(stdCode, bOnlyValid, openTag);
}

/**
 * @brief SEL策略获取K线数据
 * @details SEL策略获取指定合约的K线数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param period K线周期
 * @param barCnt K线条数
 * @param cb K线数据回调函数
 * @return WtUInt32 实际获取的K线条数
 */
WtUInt32 sel_get_bars(CtxHandler cHandle, const char* stdCode, const char* period, WtUInt32 barCnt, FuncGetBarsCallback cb)
{
	SelContextPtr ctx = getRunner().getSelContext(cHandle);
	if (ctx == NULL)
		return 0;
	try
	{
		WTSKlineSlice* kData = ctx->stra_get_bars(stdCode, period, barCnt);
		if (kData)
		{
			WtUInt32 reaCnt = (WtUInt32)kData->size();

			for (uint32_t i = 0; i < kData->get_block_counts(); i++)
				cb(cHandle, stdCode, period, kData->get_block_addr(i), kData->get_block_size(i), i == kData->get_block_counts() - 1);

			kData->release();
			return reaCnt;
		}
		else
		{
			return 0;
		}
	}
	catch (...)
	{
		return 0;
	}
}

/**
 * @brief SEL策略设置持仓
 * @details SEL策略设置指定合约的持仓数量
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param qty 目标持仓数量
 * @param userTag 用户标签
 */
void sel_set_position(CtxHandler cHandle, const char* stdCode, double qty, const char* userTag)
{
	SelContextPtr ctx = getRunner().getSelContext(cHandle);
	if (ctx == NULL)
		return;

	ctx->stra_set_position(stdCode, qty, userTag);
}

/**
 * @brief SEL策略获取tick数据
 * @details SEL策略获取指定合约的tick数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param tickCnt tick数据条数
 * @param cb tick数据回调函数
 * @return WtUInt32 实际获取的tick条数
 */
WtUInt32	sel_get_ticks(CtxHandler cHandle, const char* stdCode, WtUInt32 tickCnt, FuncGetTicksCallback cb)
{
	SelContextPtr ctx = getRunner().getSelContext(cHandle);
	if (ctx == NULL)
		return 0;
	try
	{
		WTSTickSlice* tData = ctx->stra_get_ticks(stdCode, tickCnt);
		if (tData)
		{
			uint32_t thisCnt = min(tickCnt, (WtUInt32)tData->size());
			cb(cHandle, stdCode, (WTSTickStruct*)tData->at(0), thisCnt, true);
			tData->release();
			return thisCnt;
		}
		else
		{
			return 0;
		}
	}
	catch (...)
	{
		return 0;
	}
}

/**
 * @brief SEL策略订阅tick数据
 * @details SEL策略订阅指定合约的tick数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 */
void sel_sub_ticks(CtxHandler cHandle, const char* stdCode)
{
	SelContextPtr ctx = getRunner().getSelContext(cHandle);
	if (ctx == NULL)
		return;

	ctx->stra_sub_ticks(stdCode);
}

#pragma endregion

#pragma region "HFT策略接口"

/**
 * @brief 创建HFT策略上下文
 * @details 创建指定名称的HFT策略上下文，用于策略运行
 * @param name 策略名称
 * @param trader 交易员
 * @param agent 代理
 * @return CtxHandler 策略上下文句柄
 */
CtxHandler create_hft_context(const char* name, const char* trader, bool agent)
{
	return getRunner().createHftContext(name, trader, agent);
}

/**
 * @brief HFT策略获取持仓
 * @details HFT策略获取指定合约的持仓数量
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param bOnlyValid 是否只获取有效持仓
 * @return double 持仓数量
 */
double hft_get_position(CtxHandler cHandle, const char* stdCode, bool bOnlyValid)
{
	HftContextPtr ctx = getRunner().getHftContext(cHandle);
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_position(stdCode, bOnlyValid);
}

/**
 * @brief HFT策略获取持仓盈亏
 * @details HFT策略获取指定合约的持仓盈亏
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @return double 持仓盈亏
 */
double hft_get_position_profit(CtxHandler cHandle, const char* stdCode)
{
	HftContextPtr ctx = getRunner().getHftContext(cHandle);
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_position_profit(stdCode);
}

/**
 * @brief HFT策略获取未完成交易
 * @details HFT策略获取指定合约的未完成交易数量
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @return double 未完成交易数量
 */
double hft_get_undone(CtxHandler cHandle, const char* stdCode)
{
	HftContextPtr ctx = getRunner().getHftContext(cHandle);
	if (ctx == NULL)
		return 0;

	return ctx->stra_get_undone(stdCode);
}

/**
 * @brief HFT策略获取合约价格
 * @details HFT策略获取指定合约的最新价格
 * @param stdCode 标准合约代码
 * @return double 最新价格
 */
double hft_get_price(const char* stdCode)
{
	return getRunner().getEngine()->get_cur_price(stdCode);
}

/**
 * @brief HFT策略获取当前日期
 * @details HFT策略获取当前日期
 * @return WtUInt32 当前日期（YYYYMMDD格式）
 */
WtUInt32 hft_get_date()
{
	return getRunner().getEngine()->get_date();
}

/**
 * @brief HFT策略获取当前时间
 * @details HFT策略获取当前时间
 * @return WtUInt32 当前时间（HHMM格式）
 */
WtUInt32 hft_get_time()
{
	return getRunner().getEngine()->get_raw_time();
}

/**
 * @brief HFT策略获取秒数
 * @details HFT策略获取秒数
 * @return WtUInt32 秒数
 */
WtUInt32 hft_get_secs()
{
	return getRunner().getEngine()->get_secs();
}

/**
 * @brief HFT策略获取K线数据
 * @details HFT策略获取指定合约的K线数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param period K线周期
 * @param barCnt K线条数
 * @param cb K线数据回调函数
 * @return WtUInt32 实际获取的K线条数
 */
WtUInt32 hft_get_bars(CtxHandler cHandle, const char* stdCode, const char* period, WtUInt32 barCnt, FuncGetBarsCallback cb)
{
	HftContextPtr ctx = getRunner().getHftContext(cHandle);
	if (ctx == NULL)
		return 0;

	try
	{
		WTSKlineSlice* kData = ctx->stra_get_bars(stdCode, period, barCnt);
		if (kData)
		{
			WtUInt32 reaCnt = (WtUInt32)kData->size();

			for (uint32_t i = 0; i < kData->get_block_counts(); i++)
				cb(cHandle, stdCode, period, kData->get_block_addr(i), kData->get_block_size(i), i == kData->get_block_counts() - 1);

			kData->release();
			return reaCnt;
		}
		else
		{
			return 0;
		}
	}
	catch (...)
	{
		return 0;
	}
}

/**
 * @brief HFT策略获取tick数据
 * @details HFT策略获取指定合约的tick数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param tickCnt tick数据条数
 * @param cb tick数据回调函数
 * @return WtUInt32 实际获取的tick条数
 */
WtUInt32 hft_get_ticks(CtxHandler cHandle, const char* stdCode, WtUInt32 tickCnt, FuncGetTicksCallback cb)
{
	HftContextPtr ctx = getRunner().getHftContext(cHandle);
	if (ctx == NULL)
		return 0;
	try
	{
		WTSTickSlice* tData = ctx->stra_get_ticks(stdCode, tickCnt);
		if (tData)
		{
			uint32_t thisCnt = min(tickCnt, (WtUInt32)tData->size());
			cb(cHandle, stdCode, (WTSTickStruct*)tData->at(0), thisCnt, true);
			tData->release();
			return thisCnt;
		}
		else
		{
			return 0;
		}
	}
	catch (...)
	{
		return 0;
	}
}

/**
 * @brief HFT策略获取订单队列
 * @details HFT策略获取指定合约的订单队列
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param itemCnt 项目数量
 * @param cb 订单队列回调函数
 * @return WtUInt32 实际获取的项目数量
 */
WtUInt32 hft_get_ordque(CtxHandler cHandle, const char* stdCode, WtUInt32 itemCnt, FuncGetOrdQueCallback cb)
{
	HftContextPtr ctx = getRunner().getHftContext(cHandle);
	if (ctx == NULL)
		return 0;
	try
	{
		WTSOrdQueSlice* dataSlice = ctx->stra_get_order_queue(stdCode, itemCnt);
		if (dataSlice)
		{
			uint32_t thisCnt = min(itemCnt, (WtUInt32)dataSlice->size());
			cb(cHandle, stdCode, (WTSOrdQueStruct*)dataSlice->at(0), thisCnt, true);
			dataSlice->release();
			return thisCnt;
		}
		else
		{
			return 0;
		}
	}
	catch (...)
	{
		return 0;
	}
}

/**
 * @brief HFT策略获取订单明细
 * @details HFT策略获取指定合约的订单明细
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param itemCnt 项目数量
 * @param cb 订单明细回调函数
 * @return WtUInt32 实际获取的项目数量
 */
WtUInt32 hft_get_orddtl(CtxHandler cHandle, const char* stdCode, WtUInt32 itemCnt, FuncGetOrdDtlCallback cb)
{
	HftContextPtr ctx = getRunner().getHftContext(cHandle);
	if (ctx == NULL)
		return 0;
	try
	{
		WTSOrdDtlSlice* dataSlice = ctx->stra_get_order_detail(stdCode, itemCnt);
		if (dataSlice)
		{
			uint32_t thisCnt = min(itemCnt, (WtUInt32)dataSlice->size());
			cb(cHandle, stdCode, (WTSOrdDtlStruct*)dataSlice->at(0), thisCnt, true);
			dataSlice->release();
			return thisCnt;
		}
		else
		{
			return 0;
		}
	}
	catch (...)
	{
		return 0;
	}
}

/**
 * @brief HFT策略获取逐笔成交
 * @details HFT策略获取指定合约的逐笔成交
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param itemCnt 项目数量
 * @param cb 逐笔成交回调函数
 * @return WtUInt32 实际获取的项目数量
 */
WtUInt32 hft_get_trans(CtxHandler cHandle, const char* stdCode, WtUInt32 itemCnt, FuncGetTransCallback cb)
{
	HftContextPtr ctx = getRunner().getHftContext(cHandle);
	if (ctx == NULL)
		return 0;
	try
	{
		WTSTransSlice* dataSlice = ctx->stra_get_transaction(stdCode, itemCnt);
		if (dataSlice)
		{
			uint32_t thisCnt = min(itemCnt, (WtUInt32)dataSlice->size());
			cb(cHandle, stdCode, (WTSTransStruct*)dataSlice->at(0), thisCnt, true);
			dataSlice->release();
			return thisCnt;
		}
		else
		{
			return 0;
		}
	}
	catch (...)
	{
		return 0;
	}
}

/**
 * @brief HFT策略记录日志
 * @details HFT策略记录自定义日志信息
 * @param cHandle 策略上下文句柄
 * @param message 日志消息
 */
void hft_log_text(CtxHandler cHandle, const char* message)
{
	HftContextPtr ctx = getRunner().getHftContext(cHandle);
	if (ctx == NULL)
		return;

	ctx->stra_log_info(message);
}

/**
 * @brief HFT策略订阅tick数据
 * @details HFT策略订阅指定合约的tick数据
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 */
void hft_sub_ticks(CtxHandler cHandle, const char* stdCode)
{
	HftContextPtr ctx = getRunner().getHftContext(cHandle);
	if (ctx == NULL)
		return;

	ctx->stra_sub_ticks(stdCode);
}

/**
 * @brief HFT策略订阅订单明细
 * @details HFT策略订阅指定合约的订单明细
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 */
void hft_sub_order_detail(CtxHandler cHandle, const char* stdCode)
{
	HftContextPtr ctx = getRunner().getHftContext(cHandle);
	if (ctx == NULL)
		return;

	ctx->stra_sub_order_details(stdCode);
}

/**
 * @brief HFT策略订阅订单队列
 * @details HFT策略订阅指定合约的订单队列
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 */
void hft_sub_order_queue(CtxHandler cHandle, const char* stdCode)
{
	HftContextPtr ctx = getRunner().getHftContext(cHandle);
	if (ctx == NULL)
		return;

	ctx->stra_sub_order_queues(stdCode);
}

/**
 * @brief HFT策略订阅逐笔成交
 * @details HFT策略订阅指定合约的逐笔成交
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 */
void hft_sub_transaction(CtxHandler cHandle, const char* stdCode)
{
	HftContextPtr ctx = getRunner().getHftContext(cHandle);
	if (ctx == NULL)
		return;

	ctx->stra_sub_transactions(stdCode);
}

/**
 * @brief HFT策略取消交易
 * @details HFT策略取消指定合约的交易
 * @param cHandle 策略上下文句柄
 * @param localid 本地ID
 * @return bool 取消是否成功
 */
bool hft_cancel(CtxHandler cHandle, WtUInt32 localid)
{
	HftContextPtr ctx = getRunner().getHftContext(cHandle);
	if (ctx == NULL)
		return false;

	return ctx->stra_cancel(localid);
}

/**
 * @brief HFT策略取消所有交易
 * @details HFT策略取消指定合约的所有交易
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param isBuy 是否买入
 * @return WtString 取消的本地ID列表
 */
WtString hft_cancel_all(CtxHandler cHandle, const char* stdCode, bool isBuy)
{
	HftContextPtr ctx = getRunner().getHftContext(cHandle);
	if (ctx == NULL)
		return "";

	static std::string ret;

	std::stringstream ss;
	OrderIDs ids = ctx->stra_cancel(stdCode, isBuy, DBL_MAX);
	for(uint32_t localid : ids)
	{
		ss << localid << ",";
	}

	ret = ss.str();
	if (ret.size() > 0)
		ret = ret.substr(0, ret.size() - 1);
	return ret.c_str();
}

/**
 * @brief HFT策略买入交易
 * @details HFT策略执行买入交易
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param price 价格
 * @param qty 数量
 * @param userTag 用户标签
 * @param flag 交易标志
 * @return WtString 本地ID列表
 */
WtString hft_buy(CtxHandler cHandle, const char* stdCode, double price, double qty, const char* userTag, int flag)
{
	HftContextPtr ctx = getRunner().getHftContext(cHandle);
	if (ctx == NULL)
		return "";

	static std::string ret;

	std::stringstream ss;
	OrderIDs ids = ctx->stra_buy(stdCode, price, qty, userTag, flag);
	for (uint32_t localid : ids)
	{
		ss << localid << ",";
	}

	ret = ss.str();
	if(ret.size() > 0)
		ret = ret.substr(0, ret.size() - 1);
	return ret.c_str();
}

/**
 * @brief HFT策略卖出交易
 * @details HFT策略执行卖出交易
 * @param cHandle 策略上下文句柄
 * @param stdCode 标准合约代码
 * @param price 价格
 * @param qty 数量
 * @param userTag 用户标签
 * @param flag 交易标志
 * @return WtString 本地ID列表
 */
WtString hft_sell(CtxHandler cHandle, const char* stdCode, double price, double qty, const char* userTag, int flag)
{
	HftContextPtr ctx = getRunner().getHftContext(cHandle);
	if (ctx == NULL)
		return "";

	static std::string ret;

	std::stringstream ss;
	OrderIDs ids = ctx->stra_sell(stdCode, price, qty, userTag, flag);
	for (uint32_t localid : ids)
	{
		ss << localid << ",";
	}

	ret = ss.str();
	if (ret.size() > 0)
		ret = ret.substr(0, ret.size() - 1);
	return ret.c_str();
}

/**
 * @brief HFT策略保存用户数据
 * @details HFT策略保存用户自定义数据
 * @param cHandle 策略上下文句柄
 * @param key 数据键名
 * @param val 数据值
 */
void hft_save_userdata(CtxHandler cHandle, const char* key, const char* val)
{
	HftContextPtr ctx = getRunner().getHftContext(cHandle);
	if (ctx == NULL)
		return;

	ctx->stra_save_user_data(key, val);
}

/**
 * @brief HFT策略加载用户数据
 * @details HFT策略加载用户自定义数据
 * @param cHandle 策略上下文句柄
 * @param key 数据键名
 * @param defVal 默认值
 * @return WtString 数据值
 */
WtString hft_load_userdata(CtxHandler cHandle, const char* key, const char* defVal)
{
	HftContextPtr ctx = getRunner().getHftContext(cHandle);
	if (ctx == NULL)
		return defVal;

	return ctx->stra_load_user_data(key, defVal);
}

#pragma endregion "HFT策略接口"

#pragma region "扩展Parser接口"

/**
 * @brief 推送行情数据
 * @details 外部解析器推送行情数据到系统
 * @param id 解析器ID
 * @param curTick 当前tick数据
 * @param uProcFlag 处理标志
 */
void parser_push_quote(const char* id, WTSTickStruct* curTick, WtUInt32 uProcFlag)
{
	getRunner().on_ext_parser_quote(id, curTick, uProcFlag);
}

#pragma endregion "扩展Parser接口"